/**
 * Created by zhangguoyu on 16/5/3.
 */

var mongoose = require('mongoose');
var ModelManager = require('./ModelManager');
var Utils = require('../utils/Utils');
var util = require('util');

/**
 * Model的构造器,用于辅助构建mongoose的Model对象
 * @param name Model名称
 * @constructor
 */
var ModelBuilder = function (name) {
  var self = this;
  self._name = name;
  self._schema = undefined;
  self._manager = undefined;

  self._ensureSchema = function () {
    if (arguments.length && (arguments[0] instanceof mongoose.Schema)) {
      self._schema = arguments[0];
    }
    if (self._schema === undefined) {
      self._schema = new mongoose.Schema;
    }
    return self._schema;
  }
};

/**
 * 设置Model的schema
 * http://mongoosejs.com/docs/guide.html
 * @param schema <Object, Schema>
 * @returns {ModelBuilder}
 */
ModelBuilder.prototype.schema = function (schema) {
  if (schema instanceof mongoose.Schema) {
    this._ensureSchema(schema);
  } else {
    this._ensureSchema().add(schema);
  }
  return this;
};

/**
 * 设置构建Model的options
 * http://mongoosejs.com/docs/guide.html#autoIndex
 * @param options <Object>
 * @returns {ModelBuilder}
 */
ModelBuilder.prototype.options = function (options) {
  if (options) {
    var schema = this._ensureSchema();
    for (var key in options) {
      if(!options.hasOwnProperty(key)) {
        continue;
      }
      schema.set(key, options[key]);
    }
  }
  return this;
};

/**
 * 用于以Key/Value的方式设置Model的option
 * http://mongoosejs.com/docs/api.html#schema_Schema-set
 * @param key option key
 * @param val option value
 * @returns {ModelBuilder}
 */
ModelBuilder.prototype.set = function (key, val) {
  this._ensureSchema().set(key, val);
  return this;
};

/**
 * 设置Model索引
 * http://mongoosejs.com/docs/api.html#schema_Schema-index
 * @param indexFields 索引字段
 * @param options 设置选项
 * @returns {ModelBuilder}
 */
ModelBuilder.prototype.indexs = function (indexFields, options) {
  this._ensureSchema().index(indexFields, options);
  return this;
};

/**
 * 设置Schema的实例方法
 * http://mongoosejs.com/docs/api.html#schema_Schema-method
 * @param name 方法名称
 * @param func 方法实现
 * @returns {ModelBuilder}
 */
ModelBuilder.prototype.methods = function (name, func) {
  this._ensureSchema().method(name, func);
  return this;
};

/**
 * 设置Schema的静态方法
 * http://mongoosejs.com/docs/api.html#schema_Schema-static
 * @param name 方法名称
 * @param func 方法实现
 * @returns {ModelBuilder}
 */
ModelBuilder.prototype.statics = function (name, func) {
  this._ensureSchema().static(name, func);
  return this;
};

/**
 * 设置Schema的虚拟字段
 * http://mongoosejs.com/docs/api.html#schema_Schema-virtual
 * @param name 字段名称
 * @param options 设置选项
 * @param setterFunc 虚拟字段的set方法
 * @param getterFunc 虚拟字段的get方法
 * @returns {ModelBuilder}
 */
ModelBuilder.prototype.virtual = function (name, options, setterFunc, getterFunc) {
  if (Utils.isFunction(options)) {
    getterFunc = setterFunc;
    setterFunc = options;
    options = {};
  }

  if (!options) {
    options = {};
  }
  
  var v = this._ensureSchema().virtual(name, options);
  if (Utils.isFunction(setterFunc)) {
    v.set(setterFunc);
  }
  if (Utils.isFunction(getterFunc)) {
    v.get(getterFunc);
  }
  return this;
};

/**
 * 设置Model的manager类
 * @param managerClass
 * @returns {ModelBuilder}
 */
ModelBuilder.prototype.manager = function (managerClass) {
  this._manager = managerClass;
  return this;
};

/**
 * 创建Model
 * @returns {mongoose.Model}
 */
ModelBuilder.prototype.create = function () {
  var model = mongoose.model(this._name, this._schema);
  var mng = undefined;
  var nm = this._name;
  var mnc = this._manager;
  if (mnc !== undefined) {
    mng = new mnc();
    ModelManager.call(mng, nm, model);
    if (!(mng instanceof ModelManager)) {
      util.inherits(mnc, ModelManager);
    }
  } else {
    mng = new ModelManager(nm, model);
  }
  model.prototype.$manager = model.$manager = mng;
  model.prototype.$name = model.$name = nm;
  return model;
};

module.exports = ModelBuilder;